package com.linkhub.oms.admin.modules.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.HashUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.linkhub.oms.admin.common.enums.DeclareCountryMappingTypeEnum;
import com.linkhub.oms.admin.common.enums.DeclareMethodEnum;
import com.linkhub.oms.admin.common.enums.EmployeeMenuMappingStateEnum;
import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.common.util.I18nMessageUtil;
import com.linkhub.oms.admin.modules.order.domain.param.BaseSingleOrderParam;
import com.linkhub.oms.admin.modules.order.domain.param.employee.*;
import com.linkhub.oms.admin.modules.order.domain.vo.EmployeeOrderForecastResultVO;
import com.linkhub.oms.admin.modules.order.domain.vo.EmployeeOrderPrintResultVO;
import com.linkhub.oms.admin.modules.order.domain.vo.EmployeeOrderPushToWmsResultVO;
import com.linkhub.oms.admin.modules.order.domain.vo.OrderTabCountVO;
import com.linkhub.oms.admin.modules.order.domain.vo.orderlist.OrderlistVO;
import com.linkhub.oms.admin.modules.order.service.EmployeeOrderBizService;
import com.linkhub.oms.admin.modules.order.service.OrderBizService;
import com.linkhub.oms.admin.modules.order.service.OrderExpenseBizService;
import com.linkhub.oms.admin.modules.order.service.OrderInfoAssembleService;
import com.linkhub.oms.admin.modules.order.util.OrderMappingAssist;
import com.linkhub.oms.common.constant.ShopifyConstant;
import com.linkhub.oms.common.constant.WmsInfoConstant;
import com.linkhub.oms.common.enums.IEnumConvert;
import com.linkhub.oms.common.enums.mp.*;
import com.linkhub.oms.common.exception.BizException;
import com.linkhub.oms.common.response.DataResponse;
import com.linkhub.oms.common.response.PageDTO;
import com.linkhub.oms.common.util.CacheKeyAssist;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.common.util.WmsUtil;
import com.linkhub.oms.common.util.json.QtFastjsonUtil;
import com.linkhub.oms.component.mp.util.QtMybatisPlusUtil;
import com.linkhub.oms.component.mp.wrapper.WrapperConverter;
import com.linkhub.oms.component.redis.locker.DistributedLocker;
import com.linkhub.oms.dao.mpservice.*;
import com.linkhub.oms.data.sync.api.wms.domain.dto.WmsStockOutBatchCreateDTO;
import com.linkhub.oms.data.sync.api.wms.domain.response.StockOutBatchCreateResponse;
import com.linkhub.oms.data.sync.api.yunexpress.domain.request.CreateOrderRequest;
import com.linkhub.oms.data.sync.api.yunexpress.domain.response.CreateOrderResponse;
import com.linkhub.oms.data.sync.api.yunexpress.domain.response.PrintOrderResponse;
import com.linkhub.oms.data.sync.service.OMSYunExpressApiService;
import com.linkhub.oms.data.sync.service.ShopifyDataSyncBizService;
import com.linkhub.oms.data.sync.service.WMSApiService;
import com.linkhub.oms.data.sync.util.OrderQueryColumnAssist;
import com.linkhub.oms.entity.*;
import com.linkhub.oms.entity.resulttype.OrderLocalProductResultEntity;
import com.linkhub.oms.entity.resulttype.order.OrderInfoDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static com.linkhub.oms.common.constant.WmsInfoConstant.*;
import static com.linkhub.oms.common.enums.mp.EmployeeBusinessStatusEnum.*;

/**
 * @Description: EmployeeOrderBizService
 * @Author: echo
 * @Date: 2024/4/14 11:18
 * @Version: 1.0
 */
@Slf4j
@Service
public class EmployeeOrderBizServiceImpl implements EmployeeOrderBizService {

    @Resource
    private IOrderService orderService;
    @Resource
    private OrderInfoAssembleService orderInfoAssembleService;
    @Resource
    private OrderBizService orderBizService;
    @Resource
    private DistributedLocker distributedLocker;
    @Resource
    private OrderExpenseBizService orderExpenseBizService;
    @Resource
    private OMSYunExpressApiService omsYunExpressApiService;
    @Resource
    private WMSApiService wmsApiService;
    @Resource
    private ShopifyDataSyncBizService shopifyDataSyncBizService;
    @Resource
    private IShopService shopService;
    @Resource
    private ICompanyService companyService;

    @Resource
    private IOrderProductService orderProductService;

    @Resource
    private ILocalProductService localProductService;

    @Resource
    private IShopProductSkuMappingService shopProductSkuMappingService;
    @Resource
    private IOrderAddressService orderAddressService;
    @Resource
    private IExchangeRateService exchangeRateService;

    @Override
    public PageDTO<OrderlistVO> pageOrders( EmployeeOrderQueryParam orderQueryParam ) {

        Integer tabType = orderQueryParam.getTabType();
        EmployeeBusinessStatusEnum employeeBusinessStatus = IEnumConvert.valueOf(tabType, EmployeeBusinessStatusEnum.class);
        if (Objects.isNull(employeeBusinessStatus)) {
            throw ExceptionFactory.getI18nBizException("validation.order.tabType.range");
        }

        List<String> sysShopIds = orderQueryParam.getSysShopIds();

        String orderNumber = orderQueryParam.getOrderNumber();
        EmployeeOrderStatusEnum orderStatus = IEnumConvert.valueOf(orderQueryParam.getOrderStatus(), EmployeeOrderStatusEnum.class);

        Page<OrderEntity> page = orderService.lambdaQuery()
                .in(CollUtil.isNotEmpty(sysShopIds), OrderEntity::getSysShopId, sysShopIds)
                .eq(OrderEntity::getEmployeeBusinessStatus, employeeBusinessStatus)
                .eq(Objects.nonNull(orderStatus), OrderEntity::getEmployeeOrderStatus, orderStatus)
                .like(StringUtils.isNotBlank(orderNumber), OrderEntity::getOrderNumber, orderNumber)
                .eq(OrderEntity::getDataStatus, DataStatusEnum.ENABLE)
                .orderByDesc(OrderEntity::getFulfillmentTime)
                .orderByDesc(OrderEntity::getCreatedAtConvert)
                .page(new Page<>(orderQueryParam.getPage(), orderQueryParam.getSize()));
        List<OrderEntity> records = page.getRecords();
        if (CollUtil.isEmpty(records)) {
            return QtMybatisPlusUtil.convertPage(page, null);
        }

        List<OrderInfoDO> orders = orderInfoAssembleService.assembleOrderInfos(records);

        Map<String, OrderInfoDO> orderInfoMap = QtStreamUtil.toMap(orders, OrderInfoDO::getSysOrderId);
        return QtMybatisPlusUtil.convertPage(page,
                order -> OrderMappingAssist.mappingEmployeeOrderlist(orderInfoMap.get(order.getSysOrderId())));
    }

    @Override
    public List<OrderTabCountVO> queryOrderCount( EmployeeOrderCountQueryParam orderCountQueryParam ) {
        EmployeeMenuMappingStateEnum bizStatus = IEnumConvert.valueOf(orderCountQueryParam.getMenuId(),
                EmployeeMenuMappingStateEnum.class);
        if (Objects.isNull(bizStatus)) {
            return Lists.newArrayListWithCapacity(0);
        }


        LambdaQueryWrapper<OrderEntity> lambdaQuery = Wrappers.lambdaQuery(OrderEntity.class);
        lambdaQuery
                .in(OrderEntity::getEmployeeBusinessStatus, bizStatus.getBizStatus())
                .eq(OrderEntity::getDataStatus, DataStatusEnum.ENABLE)
                .groupBy(OrderEntity::getEmployeeBusinessStatus);

        QueryWrapper<OrderEntity> queryWrapper = WrapperConverter.convertLambdaCondition(lambdaQuery);
        queryWrapper.select("Femployee_business_status, count(Fid) as count");

        List<OrderEntity> orders = orderService.list(queryWrapper);
        if (CollUtil.isEmpty(orders)) {
            return Lists.newArrayListWithCapacity(0);
        }

        return QtStreamUtil.map(orders, OrderMappingAssist::mappingEmployeeTabCount);
    }

    @Override
    public void approvalOrders( EmployeeOrderApprovalParam orderApprovalParam ) {
        String refusalReason = orderApprovalParam.getRefusalReason();
        boolean passed = Objects.equals(orderApprovalParam.getAuditResult(), BoolEnum.YES.getCode());
        if (!passed && StringUtils.isBlank(refusalReason)) {
            throw ExceptionFactory.getI18nBizException("order.employee.refusalReason.notBlank");

        }
        List<String> sysOrderIds = orderApprovalParam.getSysOrderIds();
        // 加锁
        List<String> multiLockKeys = QtStreamUtil.map(sysOrderIds, CacheKeyAssist::getEmployeeOrderApprovalLockKey);
        if (!distributedLocker.tryLockMulti(multiLockKeys)) {
            throw ExceptionFactory.getI18nBizException("approval.concurrence.problem");
        }

        try {
            if (passed) {
                passed(orderApprovalParam);
            } else {
                refusal(orderApprovalParam);
            }
        }finally {
            distributedLocker.unLockMulti(multiLockKeys);
        }
    }


    @Override
    public EmployeeOrderForecastResultVO forecastOrder( EmployeeOrderForecastParam employeeOrderForecastParam ) {
        List<OrderEntity> pendingForecastOrders = filterPendingForecastOrders(employeeOrderForecastParam);
        if (CollUtil.isEmpty(pendingForecastOrders)) {
            throw ExceptionFactory.getI18nBizException("order.submit.forecast.empty.error");
        }

        List<String> sysShopIds = QtStreamUtil.map(employeeOrderForecastParam.getShopOrders(), BaseSingleOrderParam::getSysShopId);

        // 对比可预报订单是否有带更新数据
        boolean updateFlag = orderBizService.syncOrderIfNecessary(pendingForecastOrders);

        if (updateFlag) {
            // 异步同步订单，并直接返回前端
            List<ShopEntity> shops = shopService.listBySysShopIds(sysShopIds);
            shopifyDataSyncBizService.batchAsyncPullShopProducts(shops);
            throw ExceptionFactory.getI18nBizException("order.has.update.and.sync.error");
        }

        List<String> sysOrderIds = employeeOrderForecastParam.getShopOrders().stream()
                .map(BaseSingleOrderParam::getSysOrderId)
                .collect(Collectors.toList());
        List<String> multiLockKeys = QtStreamUtil.map(sysOrderIds, CacheKeyAssist::getEmployeeOrderForecastLockKey);
        // 加锁
        if (!distributedLocker.tryLockMulti(multiLockKeys)) {
            throw ExceptionFactory.getI18nBizException("forecast.concurrence.problem");
        }
        try {
            // 查询所有需要用到的参数
            pendingForecastOrders = orderService.deepMappingOrders(pendingForecastOrders).stream()
                    .peek(ord -> {
                        ord.getOrderLineItems().forEach(orderProductEntity -> {
                            if (StringUtils.isBlank(orderProductEntity.getSkuId())) {
                                ShopProductSkuMappingEntity byShopSkuId = shopProductSkuMappingService.getByShopSkuId(orderProductEntity.getShopSkuId());
                                orderProductEntity.setSkuId(byShopSkuId.getSkuId());
                            }
                        });
                        ord.setOrderLineItems(orderProductService.deepMappingOrderProduct(ord.getOrderLineItems()));
                        ord.getOrderLineItems().forEach(op -> {
                            LocalProductEntity localProductEntity = localProductService.deepMappingLocalProduct(op.getLocalProductEntity());
                            op.setLocalProductEntity(localProductEntity);
                        });
                    })
                    .collect(Collectors.toList());

            Map<Boolean, List<OrderEntity>> partitionPendingForecastOrders = QtStreamUtil.partition(pendingForecastOrders,
                    ord -> ord.getOrderLineItems().stream().allMatch(op -> op.getLocalProductEntity() != null));

            // 云途预报接口最多接受10条记录，每次取出 10 条记录进行预报
            List<CreateOrderResponse.Item> responseItems = new ArrayList<>();
            int batchSize = 10;
            for (int i = 0; i < partitionPendingForecastOrders.get(true).size(); i += batchSize) {
                List<OrderEntity> batch = pendingForecastOrders.subList(i, Math.min(i + batchSize, pendingForecastOrders.size()));
                CreateOrderResponse createOrderResponse = processBatchForecast(batch);
                if (createOrderResponse.getItems() == null) {
                    // 批量失败组装失败信息
                    CreateOrderResponse.Item item = new CreateOrderResponse.Item();
                    for (OrderEntity order : batch) {
                        item.setCustomerOrderNumber(order.getSysOrderId());
                        item.setSuccess(0);
                        item.setRemark(createOrderResponse.getMessage());
                        responseItems.add(item);
                    }
                } else {
                    responseItems.addAll(createOrderResponse.getItems());
                }
            }

            Map<Boolean, List<CreateOrderResponse.Item>> partitionCreateOrderResponseItems = QtStreamUtil.partition(responseItems,
                    CreateOrderResponse.Item::success);

            updateFailedForecastOrderEntityStatus(partitionCreateOrderResponseItems.get(false));
            updateSuccessForecastOrderEntityStatus(partitionCreateOrderResponseItems.get(true));

            EmployeeOrderForecastResultVO employeeOrderForecastResultVO = EmployeeOrderForecastResultVO.createResult(pendingForecastOrders, partitionPendingForecastOrders, partitionCreateOrderResponseItems.get(false));
            return employeeOrderForecastResultVO;
        }finally {
            distributedLocker.unLockMulti(multiLockKeys);
        }
    }

    private void updateSuccessForecastOrderEntityStatus( List<CreateOrderResponse.Item> items ) {
        // 预报成功
        if (CollUtil.isNotEmpty(items)) {
            for (CreateOrderResponse.Item item : items) {

                orderService.lambdaUpdate()
                        .set(OrderEntity::getOrderStatus, OrderStatusEnum.TO_BE_PACKED)
                        .set(OrderEntity::getEmployeeBusinessStatus, EmployeeBusinessStatusEnum.TO_BE_PRINTED)
                        .set(OrderEntity::getEmployeeOrderStatus, EmployeeOrderStatusEnum.TO_BE_PRINTED)
                        // 保存物流单号
                        .set(OrderEntity::getWayBillNumber, item.getWayBillNumber())
                        // remark为空时也要更新为空
                        .set(OrderEntity::getFailReason, item.getRemark())
                        .eq(OrderEntity::getSysOrderId,item.getCustomerOrderNumber())
                        .update();
            }
        }
    }

    private void updateFailedForecastOrderEntityStatus( List<CreateOrderResponse.Item> items ) {
        // 预报失败
        if (CollUtil.isNotEmpty(items)) {
            for (CreateOrderResponse.Item item : items) {
                orderService.lambdaUpdate()
                        .set(OrderEntity::getOrderStatus, OrderStatusEnum.TO_BE_PACKED)
                        .set(OrderEntity::getEmployeeBusinessStatus, EmployeeBusinessStatusEnum.TO_BE_FORECAST)
                        .set(OrderEntity::getEmployeeOrderStatus, EmployeeOrderStatusEnum.FORECAST_FAILURE)
                        // remark为空时也要更新为空
                        .set(OrderEntity::getFailReason, item.getRemark())
                        .eq(OrderEntity::getSysOrderId,item.getCustomerOrderNumber())
                        .update();
            }
        }
    }

    public CreateOrderResponse processBatchForecast( List<OrderEntity> batch ) {
        List<CreateOrderRequest> createOrderRequestList = new ArrayList();
        for (OrderEntity order : batch) {
            CreateOrderRequest createOrderRequest = generateCreateOrderParam(order);
            createOrderRequestList.add(createOrderRequest);
        }

        CreateOrderResponse createOrderResponse = omsYunExpressApiService.createOrder(createOrderRequestList);
        return createOrderResponse;
    }

    public PrintOrderResponse processBatchPrint( List<OrderEntity> batch ) {
        List<String> printOrderRequestList = new ArrayList();
        for (OrderEntity order : batch) {
            printOrderRequestList.add(order.getWayBillNumber());
        }

        PrintOrderResponse printOrderResponse = omsYunExpressApiService.printOrder(printOrderRequestList);
        return printOrderResponse;
    }

    public CreateOrderRequest generateCreateOrderParam( OrderEntity order ) {
        CreateOrderRequest createOrderParam = new CreateOrderRequest();
        createOrderParam.setCustomerOrderNumber(order.getSysOrderId());
        createOrderParam.setShippingMethodCode(order.getChannelCode());
        CreateOrderRequest.ReceiverInfo receiverInfo = getReceiverInfo(order);

        createOrderParam.setReceiver(receiverInfo);

        CreateOrderRequest.SenderInfo senderInfo = getSenderInfo();
        createOrderParam.setSender(senderInfo);

        String countryCode = receiverInfo.getCountryCode();

        // 欧盟预报逻辑
        boolean isEu = DeclareCountryMappingTypeEnum.isEu(countryCode);
        if (isEu) {
            ShopEntity shopInfo = order.getShopInfo();
            List<CompanyEntity> companyEntities = companyService.listByUserId(shopInfo.getUserId());
            // 获取第一个 ioss 非空的值
            Optional<String> firstIossValue = companyEntities.stream()
                    .map(CompanyEntity::getIoss)  // 提取 ioss 属性
                    .filter(ioss -> StringUtils.isNotBlank(ioss))  // 过滤非空值
                    .findFirst();

            if (firstIossValue.isPresent()) {
                createOrderParam.setIossCode(firstIossValue.get());
            } else {
                CreateOrderRequest.OrderExtraInfo orderExtraInfo = new CreateOrderRequest.OrderExtraInfo();
                orderExtraInfo.setExtraCode("V1");
                orderExtraInfo.setExtraName("云途预缴");
                createOrderParam.setOrderExtra(Lists.newArrayList(orderExtraInfo));
            }
        }

        List<OrderProductEntity> orderProductEntities = order.getOrderLineItems();

        // 获取订单商品币种，云途要求多个产品申报信息币种必须统一
        Optional<String> firstCurrencyCode = orderProductEntities.stream()
                .map(OrderProductEntity::getCurrencyCode)  // 获取每个 OrderProductEntity 的 currencyCode
                .filter(currencyCode -> currencyCode != null && !currencyCode.isEmpty())  // 过滤非空和非空字符串
                .findFirst();  // 获取第一个非空的 currencyCode

        ArrayList<CreateOrderRequest.ParcelInfo> parcelInfos = new ArrayList<>();
        for (OrderProductEntity orderProductEntity : orderProductEntities) {
            CreateOrderRequest.ParcelInfo parcelInfo = new CreateOrderRequest.ParcelInfo();
            final LocalProductEntity localProductEntity = orderProductEntity.getLocalProductEntity();
            parcelInfo.setSKU(localProductEntity.getSku());
            parcelInfo.setEName(localProductEntity.getProductEnTitle());
            parcelInfo.setCName(localProductEntity.getProductCTitle());
            parcelInfo.setQuantity(orderProductEntity.getCurrentQuantity());
            setUnitPriceAndCurrencyCode(parcelInfo, countryCode, orderProductEntity);
            setUnitWeight(parcelInfo, localProductEntity);
            parcelInfos.add(parcelInfo);
        }
        createOrderParam.setParcels(parcelInfos);
        // 包裹总重量固定加50克
        BigDecimal unitWeightQuantitySum = parcelInfos.stream()
                .map(info -> info.getUnitWeight().multiply(BigDecimal.valueOf(info.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .add(new BigDecimal("0.05"));

        int quantitySum = parcelInfos.stream()
                .mapToInt(CreateOrderRequest.ParcelInfo::getQuantity)
                .sum();
        createOrderParam.setWeight(NumberUtil.div(unitWeightQuantitySum, 1, 3));
        createOrderParam.setPackageCount(quantitySum);
        // 临时固定设置为1，具体逻辑待与云途确认
        createOrderParam.setPackageCount(1);

        return createOrderParam;
    }

    private CreateOrderRequest.SenderInfo getSenderInfo() {
        // 固定发货人信息
        CreateOrderRequest.SenderInfo senderInfo = new CreateOrderRequest.SenderInfo();
        senderInfo.setCountryCode("CN");
        senderInfo.setFirstName("Shouyou");
        senderInfo.setLastName("Wang");
        senderInfo.setCompany("Shipo");
        senderInfo.setStreet("Qiaojiao Road, Tangxia Town");
        senderInfo.setCity("1");
        senderInfo.setState("Guangdong");
        senderInfo.setZip("523000");
        senderInfo.setPhone("15099910189");
        return senderInfo;
    }

    private void setUnitWeight( CreateOrderRequest.ParcelInfo parcelInfo, LocalProductEntity localProductEntity ) {
        try {
            // 单位 kg,单个本地产品重量，优先选仓库复核重量，没有取商家填写重量，都没有设置则为1克

            // 复核规格尺寸单位: 1-公制；2-英制    复核产品/包材信息，多个信息使用-拼接：长度(英寸)-宽度(英寸)-高度(英寸)-重量(盎司)
            Integer specificationUnitRecheck = localProductEntity.getSpecificationUnitRecheck();
            String specificationProductInfoRecheck = localProductEntity.getSpecificationProductInfoRecheck();

            Integer specificationUnit = localProductEntity.getSpecificationUnit();
            String specificationProductInfo = localProductEntity.getSpecificationProductInfo();

            if (StringUtils.isNotBlank(specificationProductInfoRecheck)) {
                String[] parts = specificationProductInfoRecheck.split("-");
                if (parts.length >= 4) {
                    BigDecimal weight = new BigDecimal(parts[3]);
                    if (specificationUnitRecheck.equals(2)) {
                        weight = weight.multiply(BigDecimal.valueOf(28.35));
                    }
                    parcelInfo.setUnitWeight(weight.divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
                }
            } else if (StringUtils.isNotBlank(specificationProductInfo)) {
                String[] parts = specificationProductInfo.split("-");
                if (parts.length >= 4) {
                    BigDecimal weight = new BigDecimal(parts[3]);
                    if (specificationUnit.equals(2)) {
                        weight = weight.multiply(BigDecimal.valueOf(28.35));
                    }
                    parcelInfo.setUnitWeight(weight.divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
                }
            } else {
                parcelInfo.setUnitWeight(BigDecimal.valueOf(0.001));
            }
        } catch (Exception e) {
            parcelInfo.setUnitWeight(BigDecimal.valueOf(0.001));
        }
    }

    private void setUnitPriceAndCurrencyCode( CreateOrderRequest.ParcelInfo parcelInfo, String countryCode, OrderProductEntity orderProduct ) {
        BigDecimal setUnitPrice;
        parcelInfo.setCurrencyCode(CurrencyTypeEnum.USD.getTypeStr());

        LocalProductEntity localProductEntity = orderProduct.getLocalProductEntity();
        // shopify商品单价
        String price = orderProduct.getPrice();
        // shopify商品单价币种
        String currencyCode = orderProduct.getCurrencyCode();
        // 本地商品采购价格
        String purchasePrice = localProductEntity.getPurchasePrice();
        // 按照产品设置申报金额规则获取单个产品价格，没设置使用shopify产品销售单价,如果是本地产品且没有设置采购价格默认为1
        if (StringUtils.isNotBlank(price) && StringUtils.isNotBlank(currencyCode)) {
//
//            List<String> allTypeStr = CurrencyTypeEnum.getAllTypeStr();
//            if (!allTypeStr.contains(currencyCode)) {
//                throw new BizException(I18nMessageUtil.getMessage("order.submit.forecast.currency.code.not.support", currencyCode));
//            }
//            //查询最近的汇率
//            List<ExchangeRateEntity> exchangeRateEntities = exchangeRateService.listExchangeRate(null);
//            if (CollUtil.isEmpty(exchangeRateEntities)) {
//                throw new BizException(I18nMessageUtil.getMessage("order.submit.forecast.currency.code.rate.not.exit", currencyCode));
//            }
//            Map<String, String> exchangeRate = exchangeRateEntities.get(0).getExchangeRate();
//
//            BigDecimal priceBD = new BigDecimal(price);
//            BigDecimal exchangeRateBD = new BigDecimal(exchangeRate.get(currencyCode));
//            setUnitPrice = priceBD.divide(exchangeRateBD, 2, RoundingMode.HALF_UP);

            BigDecimal priceBD = new BigDecimal(price);
            setUnitPrice = priceBD.divide(BigDecimal.valueOf(1), 2, RoundingMode.HALF_UP);

        } else if (StringUtils.isNotBlank(purchasePrice)) {
            setUnitPrice = new BigDecimal(purchasePrice).setScale(2, RoundingMode.HALF_UP);;
        } else {
            setUnitPrice = BigDecimal.valueOf(1);
            parcelInfo.setUnitPrice(setUnitPrice);
            return;
        }

        Integer codeByCode = DeclareCountryMappingTypeEnum.getCodeByCode(countryCode);
        List<LocalProductAmountDeclaresInfoEntity> localProductAmountDeclaresInfos = localProductEntity.getLocalProductAmountDeclaresInfos();
        Optional<LocalProductAmountDeclaresInfoEntity> result = localProductAmountDeclaresInfos.stream()
                .filter(info -> info.getDeclareCountry().equals(codeByCode))
                .findFirst();
        if (result.isPresent()) {
            // 对应国家设置了预报规则
            LocalProductAmountDeclaresInfoEntity desiredEntity = result.get();
            DeclareMethodEnum declareMethodEnum = IEnumConvert.valueOf(desiredEntity.getDeclareMethod(), DeclareMethodEnum.class);
            if (Objects.equals(declareMethodEnum, DeclareMethodEnum.FIXED)) {
                parcelInfo.setUnitPrice(desiredEntity.getDeclareValue());
            } else if (Objects.equals(declareMethodEnum, DeclareMethodEnum.RATIO)) {
                parcelInfo.setUnitPrice((setUnitPrice.multiply(desiredEntity.getDeclareValue())).setScale(2, RoundingMode.HALF_UP));
            }
        } else {
            // 对应国家没设置预报规则
            parcelInfo.setUnitPrice(setUnitPrice);
        }

    }

    private static CreateOrderRequest.ReceiverInfo getReceiverInfo( OrderEntity order ) {
        CreateOrderRequest.ReceiverInfo receiverInfo = new CreateOrderRequest.ReceiverInfo();

        OrderAddressEntity orderAddress = order.getOrderAddress();
        receiverInfo.setCountryCode(orderAddress.getCountryCode()); // 必填
        receiverInfo.setFirstName(orderAddress.getName()); // 必填
        receiverInfo.setCompany(orderAddress.getCompany());
        receiverInfo.setStreet(orderAddress.getAddress1()); // 必填
        receiverInfo.setCity(orderAddress.getCity());
        receiverInfo.setState(orderAddress.getProvince());
        receiverInfo.setZip(orderAddress.getZip());
        receiverInfo.setPhone(orderAddress.getPhone());
        receiverInfo.setEmail(order.getEmail());
        return receiverInfo;
    }

    @Override
    public EmployeeOrderPushToWmsResultVO pushToWms( EmployeeOrderPushToWmsParam employeeOrderPushToWmsParam ) {

        List<OrderEntity> pendingPushToWmsOrders = filterPendingPushToWmsOrders(employeeOrderPushToWmsParam);
        if (CollUtil.isEmpty(pendingPushToWmsOrders)) {
            throw ExceptionFactory.getI18nBizException("order.submit.push.to.wms.empty.error");
        }

        List<String> sysShopIds = QtStreamUtil.map(employeeOrderPushToWmsParam.getShopOrders(), BaseSingleOrderParam::getSysShopId);

        // 对比可推送订单是否有带更新数据
        boolean updateFlag = orderBizService.syncOrderIfNecessary(pendingPushToWmsOrders);

        if (updateFlag) {
            // 异步同步订单，并直接返回前端
            List<ShopEntity> shops = shopService.listBySysShopIds(sysShopIds);
            shopifyDataSyncBizService.batchAsyncPullShopProducts(shops);
            throw ExceptionFactory.getI18nBizException("order.has.update.and.sync.error");
        }

        List<String> sysOrderIds = employeeOrderPushToWmsParam.getShopOrders().stream()
                .map(BaseSingleOrderParam::getSysOrderId)
                .collect(Collectors.toList());
        List<String> multiLockKeys = QtStreamUtil.map(sysOrderIds, CacheKeyAssist::getEmployeePushToWmsLockKey);
        // 加锁
        if (!distributedLocker.tryLockMulti(multiLockKeys)) {
            throw ExceptionFactory.getI18nBizException("push.to.wms.response.fail");
        }

        try {
            WmsStockOutBatchCreateDTO wmsCreateDeliveryListDTO = new WmsStockOutBatchCreateDTO();
            List<WmsStockOutBatchCreateDTO.Order> orders = Lists.newArrayList();
            wmsCreateDeliveryListDTO.setOrders(orders);
//            String outBizCode = "";
            // 查询出商店信息
            pendingPushToWmsOrders = orderService.deepMappingOrders(pendingPushToWmsOrders);
            for (OrderEntity orderEntity : pendingPushToWmsOrders) {
//                outBizCode += orderEntity.getId();
                WmsStockOutBatchCreateDTO.Order order = new WmsStockOutBatchCreateDTO.Order();
                orders.add(order);
                WmsStockOutBatchCreateDTO.Order.DeliveryOrder deliveryOrder = new WmsStockOutBatchCreateDTO.Order.DeliveryOrder();
                WmsStockOutBatchCreateDTO.Order.OrderLines orderLines = new WmsStockOutBatchCreateDTO.Order.OrderLines();
                order.setDeliveryOrder(deliveryOrder);
                order.setOrderLines(orderLines);
                deliveryOrder.setDeliveryOrderCode(orderEntity.getSysOrderId());
                deliveryOrder.setOrderType(WmsInfoConstant.XSDD);
                deliveryOrder.setWarehouseCode(WmsInfoConstant.WAREHOUSE_CODE);
                deliveryOrder.setOwnerCode(WmsInfoConstant.OWNER_CODE);

                final PlatFormEnum platForm = orderEntity.getShopInfo().getPlatForm();
                if (platForm != null) {
                    deliveryOrder.setSourcePlatformCode(platForm.getDesc());
                } else {
                    deliveryOrder.setSourcePlatformCode("Shopify");
                }
                
                deliveryOrder.setLogisticsCode("YT");
                deliveryOrder.setExpressCode(orderEntity.getWayBillNumber());
                deliveryOrder.setBuyerMessage(orderEntity.getBuyerNote());
                deliveryOrder.setSellerMessage(orderEntity.getSellerNote());
                ShopEntity shopEntity = shopService.getByShopId(orderEntity.getSysShopId());
                deliveryOrder.setUserDefined1(shopEntity.getUserId());
                deliveryOrder.setSenderInfo(getSenderInfo(shopEntity));
                OrderAddressEntity orderAddressEntity = orderAddressService.getByOrderIds(orderEntity.getSysOrderId());
                deliveryOrder.setReceiverInfo(getReceiverInfo(orderAddressEntity));
                WmsStockOutBatchCreateDTO.Order.DeliveryOrder.Files files = new WmsStockOutBatchCreateDTO.Order.DeliveryOrder.Files();
                deliveryOrder.setFiles(files);
                List<WmsStockOutBatchCreateDTO.Order.DeliveryOrder.Files.File> fileList = Lists.newArrayList();
                files.setFile(fileList);
                WmsStockOutBatchCreateDTO.Order.DeliveryOrder.Files.File file = new WmsStockOutBatchCreateDTO.Order.DeliveryOrder.Files.File();
                file.setName(PACKING_LIST_PDF_NAME);
                file.setUrl(orderEntity.getPackagePdfUrl());
                fileList.add(file);
//                WmsStockOutBatchCreateDTO.Order.DeliveryOrder.Files.File file1 = new WmsStockOutBatchCreateDTO.Order.DeliveryOrder.Files.File();
//                file1.setName("运单.pdf");
//                file1.setUrl(orderEntity.getWayBillPdfFile());
//                fileList.add(file1);
                deliveryOrder.setCustomJson(CUSTOM_JSON_STRING.replace(SHIPPING_LABEL_PDF_NAME, orderEntity.getWayBillPdfFile()));

//                List<OrderLocalProductResultEntity> orderProductEntities = orderProductService.listOrderLocalProducts(Lists.newArrayList(orderEntity.getSysOrderId()));

                List<OrderProductEntity> orderProductEntities1 = orderProductService.listBySysOrderId(orderEntity.getSysOrderId());
                orderProductEntities1 = orderProductEntities1.stream()
                        .peek(ord -> {
                            if (StringUtils.isBlank(ord.getSkuId())) {
                                ShopProductSkuMappingEntity byShopSkuId = shopProductSkuMappingService.getByShopSkuId(ord.getShopSkuId());
                                ord.setSkuId(byShopSkuId.getSkuId());
                            }

                        }).collect(Collectors.toList());

                List<WmsStockOutBatchCreateDTO.Order.OrderLines.OrderLine> orderLineList = Lists.newArrayList();
                orderLines.setOrderLine(orderLineList);

                for (OrderProductEntity orderProduct : orderProductEntities1) {
                    WmsStockOutBatchCreateDTO.Order.OrderLines.OrderLine orderLine = new WmsStockOutBatchCreateDTO.Order.OrderLines.OrderLine();
                    orderLineList.add(orderLine);

                    orderLine.setItemCode(WmsUtil.createItemCode(shopEntity.getUserId(), orderProduct.getSkuId()));
                    orderLine.setPlanQty(String.valueOf(orderProduct.getCurrentQuantity()));
//                    orderLine.setStockinDate(DateUtil.formatDate(new Date()));
                    orderLine.setUserDefined1(shopEntity.getUserId());
                }
//                for (OrderLocalProductResultEntity orderLineItem : orderProductEntities) {
//                    WmsStockOutBatchCreateDTO.Order.OrderLines.OrderLine orderLine = new WmsStockOutBatchCreateDTO.Order.OrderLines.OrderLine();
//                    orderLineList.add(orderLine);
//
//                    orderLine.setItemCode(WmsUtil.createItemCode(shopEntity.getUserId(), orderLineItem.getSkuId()));
//                    orderLine.setPlanQty(String.valueOf(orderLineItem.getCurrentQuantity()));
//                    orderLine.setStockinDate(DateUtil.formatDate(new Date()));
//                }
            }
            wmsCreateDeliveryListDTO.setOutBizCode(IdUtil.getSnowflake().nextIdStr());

            StockOutBatchCreateResponse stockOutBatchCreateResponse = wmsApiService.batchCreateStockOutList(wmsCreateDeliveryListDTO);
            if (!stockOutBatchCreateResponse.success()) {
                log.error("出库单创建失败，response: {}", QtFastjsonUtil.toJSONString(stockOutBatchCreateResponse));
                throw ExceptionFactory.getI18nBizException("push.to.wms.response.fail");
            }

            List<String> pendingPushToWmsOrderIds = pendingPushToWmsOrders.stream()
                    .map(OrderEntity::getSysOrderId)
                    .collect(Collectors.toList());
            EmployeeOrderPushToWmsResultVO employeeOrderPushToWmsResultVO;

            if (stockOutBatchCreateResponse.success()) {
                // 推送成功,如果接口推送成功，则是全部成功
                orderService.lambdaUpdate()
                        .set(OrderEntity::getOrderStatus, OrderStatusEnum.TO_BE_PACKED)
                        .set(OrderEntity::getEmployeeBusinessStatus, EmployeeBusinessStatusEnum.TO_BE_PACKAGED)
                        .set(OrderEntity::getEmployeeOrderStatus, EmployeeOrderStatusEnum.TO_BE_PACKED)
                        // 推送成功，失败原因都置空
                        .set(OrderEntity::getFailReason, null)
                        .in(OrderEntity::getSysOrderId, pendingPushToWmsOrderIds)
                        .update();
                employeeOrderPushToWmsResultVO = EmployeeOrderPushToWmsResultVO.createResult(pendingPushToWmsOrders, null);
            } else {
                // 推送失败，如果接口推送失败，则是全部失败
                List<StockOutBatchCreateResponse.Order> orderList = stockOutBatchCreateResponse.getResponse().getOrders().getOrder();

                Map<String,String> failReasonMap = QtStreamUtil.toMap(orderList,StockOutBatchCreateResponse.Order::getDeliveryOrderCode,StockOutBatchCreateResponse.Order::getMessage);

                pendingPushToWmsOrderIds.forEach(orderId -> orderService.lambdaUpdate()
                        .set(OrderEntity::getOrderStatus, OrderStatusEnum.TO_BE_PACKED)
                        .set(OrderEntity::getEmployeeBusinessStatus, EmployeeBusinessStatusEnum.TO_BE_PUSHED)
                        .set(OrderEntity::getEmployeeOrderStatus, EmployeeOrderStatusEnum.PUSH_FAILURE)
                        .set(OrderEntity::getFailReason, failReasonMap.get(orderId))
                        .eq(OrderEntity::getSysOrderId, orderId)
                        .update());

                employeeOrderPushToWmsResultVO = EmployeeOrderPushToWmsResultVO.createResult(pendingPushToWmsOrders, orderList);
            }

            return employeeOrderPushToWmsResultVO;
        }finally {
            distributedLocker.unLockMulti(multiLockKeys);
        }
    }

    private WmsStockOutBatchCreateDTO.Order.DeliveryOrder.SenderInfo getSenderInfo( ShopEntity shopEntity ) {
        WmsStockOutBatchCreateDTO.Order.DeliveryOrder.SenderInfo senderInfo = new WmsStockOutBatchCreateDTO.Order.DeliveryOrder.SenderInfo();
        senderInfo.setCompany(shopEntity.getShopName());
        senderInfo.setName(shopEntity.getUserId());
        senderInfo.setCountryCode("CN");
        senderInfo.setMobile("15099910189");
        senderInfo.setZipCode("523000");
        senderInfo.setProvince("Guangdong");
        senderInfo.setCity("dongguan");
        senderInfo.setArea("T-AREA");
        senderInfo.setTown("207 E TELLURIDE DR");
        senderInfo.setDetailAddress("Qiaojiao Road, Tangxia Town");
        senderInfo.setCompany("Shipo");
        return senderInfo;
    }

    private WmsStockOutBatchCreateDTO.Order.DeliveryOrder.ReceiverInfo getReceiverInfo( OrderAddressEntity orderAddressEntity ) {
        WmsStockOutBatchCreateDTO.Order.DeliveryOrder.ReceiverInfo receiverInfo = new WmsStockOutBatchCreateDTO.Order.DeliveryOrder.ReceiverInfo();
        receiverInfo.setCompany(orderAddressEntity.getCompany());
        receiverInfo.setName(orderAddressEntity.getName());
        receiverInfo.setZipCode(orderAddressEntity.getZip());
        receiverInfo.setTel(orderAddressEntity.getPhone());
        receiverInfo.setMobile(orderAddressEntity.getPhone());
        receiverInfo.setCountryCode(orderAddressEntity.getCountryCode());
        receiverInfo.setProvince(orderAddressEntity.getProvince());
        receiverInfo.setCity(orderAddressEntity.getCity());
        receiverInfo.setArea("AREA");
        receiverInfo.setTown("TOWN");
        receiverInfo.setDetailAddress(StringUtils.defaultIfBlank(orderAddressEntity.getAddress1(), orderAddressEntity.getAddress2()));
        receiverInfo.setOaid("T-OAID");
        return receiverInfo;
    }

    @Override
    public EmployeeOrderPrintResultVO printOrder( EmployeeOrderPrintParam employeeOrderPrintParam ) {
        List<OrderEntity> pendingPrintOrders = filterPendingPrintOrders(employeeOrderPrintParam);
        if (CollUtil.isEmpty(pendingPrintOrders)) {
            throw ExceptionFactory.getI18nBizException("order.submit.print.empty.error");
        }

        List<String> sysShopIds = QtStreamUtil.map(employeeOrderPrintParam.getShopOrders(), BaseSingleOrderParam::getSysShopId);

        // 对比可提交履约订单是否有带更新数据
        boolean updateFlag = orderBizService.syncOrderIfNecessary(pendingPrintOrders);

        if (updateFlag) {
            // 异步同步订单，并直接返回前端
            List<ShopEntity> shops = shopService.listBySysShopIds(sysShopIds);
            shopifyDataSyncBizService.batchAsyncPullShopProducts(shops);
            throw ExceptionFactory.getI18nBizException("order.has.update.and.sync.error");
        }

        List<String> sysOrderIds = employeeOrderPrintParam.getShopOrders().stream()
                .map(BaseSingleOrderParam::getSysOrderId)
                .collect(Collectors.toList());
        List<String> multiLockKeys = QtStreamUtil.map(sysOrderIds, CacheKeyAssist::getEmployeeOrderPrintLockKey);
        // 加锁
        if (!distributedLocker.tryLockMulti(multiLockKeys)) {
            throw ExceptionFactory.getI18nBizException("print.concurrence.problem");
        }
        try {

            Map<Boolean, List<OrderEntity>> partitionPendingPrintOrders = QtStreamUtil.partition(pendingPrintOrders,
                    ord -> StringUtils.isNotBlank(ord.getWayBillNumber()));

            // 云途打印接口最多接受50条记录，每次取出 50 条记录进行预报（更正：批量打印是多个运单号生成一个pdf，需要是一个运单号生成一个pdf）
            List<PrintOrderResponse.DefinePrintResult> definePrintResults = new ArrayList<>();
            int batchSize = 1;
            for (int i = 0; i < partitionPendingPrintOrders.get(true).size(); i += batchSize) {
                List<OrderEntity> batch = partitionPendingPrintOrders.get(true).subList(i, Math.min(i + batchSize, partitionPendingPrintOrders.get(true).size()));
                PrintOrderResponse printOrderResponse = processBatchPrint(batch);
                if (printOrderResponse.getItems() == null) {
                    // 批量失败组装失败信息
                    for (OrderEntity order : batch) {
                        PrintOrderResponse.DefinePrintResult definePrintResult = getDefinePrintResult(order, printOrderResponse);
                        definePrintResults.add(definePrintResult);
                    }
                } else {
                    for (PrintOrderResponse.Item item : printOrderResponse.getItems()) {
                        PrintOrderResponse.DefinePrintResult definePrintResult = new PrintOrderResponse.DefinePrintResult();
                        PrintOrderResponse.DefinePrintResult.OrderNumberMess orderNumberMess = new PrintOrderResponse.DefinePrintResult.OrderNumberMess();
                        List<PrintOrderResponse.Item.OrderInfo> orderInfos = item.getOrderInfos();
                        // 取第一个信息（需与云途接口返回逻辑确认）
                        if (Objects.nonNull(orderInfos)) {
                            PrintOrderResponse.Item.OrderInfo orderInfo = orderInfos.get(0);
                            definePrintResult.setCustomerOrderNumber(orderInfo.getCustomerOrderNumber());
                            orderNumberMess.setCode(orderInfo.getCode());
                            orderNumberMess.setError(orderInfo.getError());
                            orderNumberMess.setUrl(item.getUrl());
                            definePrintResult.setOrderNumberMess(orderNumberMess);
                            definePrintResults.add(definePrintResult);
                        } else {
                            // 如果返回列表为空将无法识别具体是哪个订单失败
                        }
                    }
                }
            }

            Map<Boolean, List<PrintOrderResponse.DefinePrintResult>> partitionDefinePrintResults = QtStreamUtil.partition(definePrintResults,
                    result -> result.getOrderNumberMess().success());

            // 创建一个 wayBillNumber 到 sysOrderId 的映射
            Map<String, String> wayBillNumberToSysOrderIdMap = pendingPrintOrders.stream()
                    .collect(Collectors.toMap(OrderEntity::getWayBillNumber, OrderEntity::getSysOrderId));
            updateFailedPrintOrderEntityStatus(wayBillNumberToSysOrderIdMap, partitionDefinePrintResults.get(false));
            updateSuccessPrintOrderEntityStatus(wayBillNumberToSysOrderIdMap, partitionDefinePrintResults.get(true));

            EmployeeOrderPrintResultVO employeeOrderPrintResultVO = EmployeeOrderPrintResultVO
                    .createResult(pendingPrintOrders, partitionDefinePrintResults);
            return employeeOrderPrintResultVO;
        }finally {
            distributedLocker.unLockMulti(multiLockKeys);
        }
    }

    private void updateSuccessPrintOrderEntityStatus( Map<String, String> wayBillNumberToSysOrderIdMap, List<PrintOrderResponse.DefinePrintResult> definePrintResults ) {
        // 打印成功
        if (CollUtil.isNotEmpty(definePrintResults)) {
            for (PrintOrderResponse.DefinePrintResult definePrintResult : definePrintResults) {
                orderService.lambdaUpdate()
                        .set(OrderEntity::getOrderStatus, OrderStatusEnum.TO_BE_PACKED)
                        .set(OrderEntity::getEmployeeBusinessStatus, EmployeeBusinessStatusEnum.TO_BE_PUSHED)
                        .set(OrderEntity::getEmployeeOrderStatus, EmployeeOrderStatusEnum.TO_BE_PUSHED)
                        // 保存运单pdf链接
                        .set(OrderEntity::getWayBillPdfFile, definePrintResult.getOrderNumberMess().getUrl())
                        // 更新失败原因，为空也要更新空
                        .set(OrderEntity::getFailReason, definePrintResult.getOrderNumberMess().getError())
                        .eq(OrderEntity::getSysOrderId, wayBillNumberToSysOrderIdMap.get(definePrintResult.getCustomerOrderNumber()))
                        .update();
            }
        }
    }

    private void updateFailedPrintOrderEntityStatus( Map<String, String> wayBillNumberToSysOrderIdMap, List<PrintOrderResponse.DefinePrintResult> definePrintResults ) {
        // 打印失败
        if (CollUtil.isNotEmpty(definePrintResults)) {
            for (PrintOrderResponse.DefinePrintResult definePrintResult : definePrintResults) {
                orderService.lambdaUpdate()
                        .set(OrderEntity::getOrderStatus, OrderStatusEnum.TO_BE_PACKED)
                        .set(OrderEntity::getEmployeeBusinessStatus, EmployeeBusinessStatusEnum.TO_BE_PRINTED)
                        .set(OrderEntity::getEmployeeOrderStatus, EmployeeOrderStatusEnum.PRINT_FAILURE)
                        // 更新失败原因，为空也要更新空
                        .set(OrderEntity::getFailReason, definePrintResult.getOrderNumberMess().getError())
                        .eq(OrderEntity::getSysOrderId, wayBillNumberToSysOrderIdMap.get(definePrintResult.getCustomerOrderNumber()))
                        .update();
            }
        }
    }

    private static PrintOrderResponse.DefinePrintResult getDefinePrintResult( OrderEntity order, PrintOrderResponse printOrderResponse ) {
        PrintOrderResponse.DefinePrintResult definePrintResult = new PrintOrderResponse.DefinePrintResult();
        definePrintResult.setCustomerOrderNumber(order.getSysOrderId());
        PrintOrderResponse.DefinePrintResult.OrderNumberMess orderNumberMess = new PrintOrderResponse.DefinePrintResult.OrderNumberMess();
        orderNumberMess.setCode(200);
        orderNumberMess.setError(printOrderResponse.getMessage());
        definePrintResult.setOrderNumberMess(orderNumberMess);
        return definePrintResult;
    }

    private void passed( EmployeeOrderApprovalParam orderApprovalParam ) {

        OrderEntity pass = new OrderEntity();
        pass.setOrderStatus(OrderStatusEnum.TO_BE_PACKED);
        pass.setEmployeeBusinessStatus(EmployeeBusinessStatusEnum.TO_BE_FORECAST);
        pass.setEmployeeOrderStatus(EmployeeOrderStatusEnum.TO_BE_FORECAST);
        orderService.updateOrderInfos(orderApprovalParam.getSysOrderIds(), pass);

    }

    private void refusal( EmployeeOrderApprovalParam orderApprovalParam ) {

        OrderEntity refusal = new OrderEntity();
        refusal.setRefusalReason(orderApprovalParam.getRefusalReason());
        refusal.setOrderStatus(OrderStatusEnum.REJECTED);
        refusal.setCustomerBusinessStatus(CustomerBusinessStatusEnum.ABNORMAL);
        refusal.setEmployeeBusinessStatus(EmployeeBusinessStatusEnum.CUSTOMER_NOT_PERFORMING);
        refusal.setEmployeeOrderStatus(EmployeeOrderStatusEnum.VOID);
        // TODO: echo_3.0 如果库存有货，需要释放预占库存 通过事件来实现
        orderService.updateOrderInfos(orderApprovalParam.getSysOrderIds(), refusal);
        orderApprovalParam.getSysOrderIds().forEach(orderExpenseBizService::thawOrderExpense);
    }

    private List<OrderEntity> filterPendingForecastOrders( EmployeeOrderForecastParam employeeOrderForecastParam ) {
        List<BaseSingleOrderParam> shopOrders = employeeOrderForecastParam.getShopOrders();
        List<String> sysOrderIds = QtStreamUtil.mapAndDistinct(shopOrders, BaseSingleOrderParam::getSysOrderId);
        List<String> sysShopIds = QtStreamUtil.mapAndDistinct(shopOrders, BaseSingleOrderParam::getSysShopId);

        List<OrderEntity> orders = orderService.listShopOrders(sysShopIds,
                sysOrderIds, OrderQueryColumnAssist.queryOrderForecastColumns());

        List<OrderEntity> pendingForecastOrders = QtStreamUtil.filter(orders,
                // 待预报订单
                order -> isPendingForecast(order.getEmployeeBusinessStatus()));
        return pendingForecastOrders;
    }

    private List<OrderEntity> filterPendingPrintOrders( EmployeeOrderPrintParam employeeOrderPrintParam ) {
        List<BaseSingleOrderParam> shopOrders = employeeOrderPrintParam.getShopOrders();
        List<String> sysOrderIds = QtStreamUtil.mapAndDistinct(shopOrders, BaseSingleOrderParam::getSysOrderId);
        List<String> sysShopIds = QtStreamUtil.mapAndDistinct(shopOrders, BaseSingleOrderParam::getSysShopId);

        List<OrderEntity> orders = orderService.listShopOrders(sysShopIds,
                sysOrderIds, OrderQueryColumnAssist.queryOrderPrintColumns());

        List<OrderEntity> pendingPrintOrders = QtStreamUtil.filter(orders,
                // 待打印订单
                order -> isPendingPrint(order.getEmployeeBusinessStatus()));
        return pendingPrintOrders;
    }

    private List<OrderEntity> filterPendingPushToWmsOrders( EmployeeOrderPushToWmsParam employeeOrderPushToWmsParam ) {
        List<BaseSingleOrderParam> shopOrders = employeeOrderPushToWmsParam.getShopOrders();
        List<String> sysOrderIds = QtStreamUtil.mapAndDistinct(shopOrders, BaseSingleOrderParam::getSysOrderId);
        List<String> sysShopIds = QtStreamUtil.mapAndDistinct(shopOrders, BaseSingleOrderParam::getSysShopId);

        List<OrderEntity> orders = orderService.listShopOrders(sysShopIds,
                sysOrderIds, OrderQueryColumnAssist.queryOrderPushToWmsColumns());

        List<OrderEntity> pendingPushToWmsOrders = QtStreamUtil.filter(orders,
                // 待推送订单
                order -> isPendingPushToWms(order.getEmployeeBusinessStatus()));
        return pendingPushToWmsOrders;
    }

}
